#!/usr/bin/env python3
"""
内容发布和管理接口
"""

from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from typing import List, Optional, Dict
from pydantic import BaseModel
from datetime import datetime
import os

from models import get_db, User, Content, ContentTag, ContentMedia, Tag
from views import get_current_user
from services.es_client import ESClient
from services.chunk_upload_service import chunk_upload_service
from config.minio_config import minio_client

router = APIRouter()
security = HTTPBearer()

# 请求/响应模型
class MediaInfo(BaseModel):
    """媒体信息"""
    url: str
    media_type: str  # image/video
    width: Optional[int] = None
    height: Optional[int] = None
    file_size: Optional[int] = None
    duration: Optional[int] = None  # 视频时长（秒）

class ContentPublishRequest(BaseModel):
    """发布内容请求"""
    title: str
    description: Optional[str] = None
    tag_ids: List[int] = []
    status: int = 1  # 1=草稿，2=已发布
    
class ContentPublishResponse(BaseModel):
    """发布内容响应"""
    success: bool
    message: str
    content_id: Optional[int] = None

class ContentItem(BaseModel):
    """内容项"""
    id: int
    title: str
    description: str
    author_id: int
    author_nickname: str
    status: int
    view_count: int
    like_count: int
    comment_count: int
    share_count: int
    collect_count: int
    first_image_url: Optional[str]
    tag_names: List[str]
    created_at: str
    published_at: Optional[str]

class ContentListResponse(BaseModel):
    """内容列表响应"""
    success: bool
    data: List[ContentItem]
    total: int
    page: int
    size: int

class MediaItem(BaseModel):
    """媒体项"""
    url: str
    media_type: str
    width: Optional[int] = None
    height: Optional[int] = None
    file_size: Optional[int] = None
    duration: Optional[int] = None

class ContentDetailResponse(BaseModel):
    """内容详情响应"""
    success: bool
    data: Optional[Dict] = None
    message: Optional[str] = None

# 创建ES客户端实例（在函数内部初始化，避免全局变量问题）
# es_client = ESClient(use_async=False)

@router.post("/content/publish", response_model=ContentPublishResponse)
async def publish_content(
    title: str = Form(...),
    description: str = Form(None),
    tag_ids: str = Form("[]"),  # JSON字符串
    status: int = Form(2),  # 默认已发布
    files: List[UploadFile] = File(...),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """发布内容（包含图片/视频）"""
    try:
        import json
        tag_ids_list = json.loads(tag_ids)
        
        # 验证标题
        if not title or len(title.strip()) == 0:
            return ContentPublishResponse(
                success=False,
                message="标题不能为空"
            )
        
        # 验证标签
        if tag_ids_list:
            valid_tags = db.query(Tag).filter(Tag.id.in_(tag_ids_list)).all()
            if len(valid_tags) != len(tag_ids_list):
                return ContentPublishResponse(
                    success=False,
                    message="无效的标签ID"
                )
        
        # 保存上传的文件
        media_list = []
        upload_dir = "static/uploads"
        os.makedirs(upload_dir, exist_ok=True)
        
        for idx, file in enumerate(files, start=1):
            # 生成文件名
            ext = os.path.splitext(file.filename)[1]
            filename = f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{current_user.id}_{idx}{ext}"
            filepath = os.path.join(upload_dir, filename)
            
            # 保存文件
            with open(filepath, "wb") as f:
                content = await file.read()
                f.write(content)
            
            # 判断媒体类型
            if ext.lower() in ['.jpg', '.jpeg', '.png', '.gif', '.webp']:
                media_type = "image"
            elif ext.lower() in ['.mp4', '.mov', '.avi', '.webm']:
                media_type = "video"
            else:
                media_type = "image"  # 默认
            
            # 获取文件信息
            file_size = os.path.getsize(filepath)
            media_url = f"/static/uploads/{filename}"
            
            media_list.append({
                "media_url": media_url,
                "media_type": media_type,
                "sort_order": idx,
                "file_size": file_size
            })
        
        if not media_list:
            return ContentPublishResponse(
                success=False,
                message="至少上传一张图片"
            )
        
        # 创建内容记录
        content = Content(
            title=title,
            description=description or "",
            author_id=current_user.id,
            status=status,
            published_at=datetime.utcnow() if status == 2 else None
        )
        
        db.add(content)
        db.flush()  # 获取content.id
        
        # 创建标签关联
        for tag_id in tag_ids_list:
            content_tag = ContentTag(
                content_id=content.id,
                tag_id=tag_id
            )
            db.add(content_tag)
        
        # 创建媒体记录
        for media in media_list:
            content_media = ContentMedia(
                content_id=content.id,
                media_url=media["media_url"],
                media_type=media["media_type"],
                sort_order=media["sort_order"],
                file_size=media.get("file_size")
            )
            db.add(content_media)
        
        db.commit()
        db.refresh(content)
        
        # 同步到ES（如果是已发布状态）
        if status == 2:
            try:
                # 获取标签名称
                tag_names = db.query(Tag.name).filter(Tag.id.in_(tag_ids_list)).all()
                tag_names_list = [tag[0] for tag in tag_names]
                
                es_doc = {
                    "content_id": content.id,
                    "title": content.title,
                    "description": content.description or "",
                    "author_id": content.author_id,
                    "author_nickname": current_user.nickname,
                    "tag_ids": tag_ids_list,
                    "tag_names": tag_names_list,
                    "status": content.status,
                    "view_count": content.view_count,
                    "like_count": content.like_count,
                    "comment_count": content.comment_count,
                    "share_count": content.share_count,
                    "collect_count": content.collect_count,
                    "first_image_url": media_list[0]["media_url"] if media_list else None,
                    "media_urls": [m["media_url"] for m in media_list],
                    "media_types": [m["media_type"] for m in media_list],
                    "is_top": content.is_top,
                    "created_at": content.created_at.isoformat() if content.created_at else None,
                    "published_at": content.published_at.isoformat() if content.published_at else None
                }
                
                # 同步到ES（使用同步方式）
                es_client = ESClient(use_async=False)
                import asyncio
                try:
                    # 直接调用同步方法
                    result = es_client.es.index(
                        index="content_recommend",
                        id=content.id,
                        body=es_doc
                    )
                    print(f"✓ 成功同步内容 {content.id} 到ES")
                except Exception as sync_error:
                    print(f"✗ ES同步失败: {sync_error}")
                
            except Exception as e:
                print(f"同步到ES失败: {e}")
                # ES同步失败不影响主流程
        
        return ContentPublishResponse(
            success=True,
            message="发布成功",
            content_id=content.id
        )
        
    except Exception as e:
        print(f"发布内容失败: {e}")
        db.rollback()
        return ContentPublishResponse(
            success=False,
            message=f"发布失败: {str(e)}"
        )

@router.get("/content/list", response_model=ContentListResponse)
async def get_content_list(
    page: int = 1,
    size: int = 20,
    status: int = 2,  # 默认获取已发布内容
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取内容列表"""
    try:
        # 计算分页
        from_ = (page - 1) * size
        
        # 查询内容
        query = db.query(Content).filter(Content.status == status)
        
        # 如果不是查看自己的内容，只显示已发布的内容
        if status == 2:
            query = query.filter(Content.status == 2)
        
        total = query.count()
        contents = query.order_by(Content.created_at.desc()).offset(from_).limit(size).all()
        
        # 格式化响应
        content_list = []
        for content in contents:
            # 获取首图
            first_media = db.query(ContentMedia).filter(
                ContentMedia.content_id == content.id
            ).order_by(ContentMedia.sort_order).first()
            
            # 获取标签
            content_tags = db.query(ContentTag).filter(
                ContentTag.content_id == content.id
            ).all()
            tag_ids = [ct.tag_id for ct in content_tags]
            
            tag_names = []
            if tag_ids:
                tags = db.query(Tag.name).filter(Tag.id.in_(tag_ids)).all()
                tag_names = [tag[0] for tag in tags]
            
            # 获取作者昵称
            author = db.query(User).filter(User.id == content.author_id).first()
            
            content_list.append(ContentItem(
                id=content.id,
                title=content.title,
                description=content.description or "",
                author_id=content.author_id,
                author_nickname=author.nickname if author else "未知",
                status=content.status,
                view_count=content.view_count,
                like_count=content.like_count,
                comment_count=content.comment_count,
                share_count=content.share_count,
                collect_count=content.collect_count,
                first_image_url=first_media.media_url if first_media else None,
                tag_names=tag_names,
                created_at=content.created_at.isoformat() if content.created_at else "",
                published_at=content.published_at.isoformat() if content.published_at else None
            ))
        
        return ContentListResponse(
            success=True,
            data=content_list,
            total=total,
            page=page,
            size=size
        )
        
    except Exception as e:
        print(f"获取内容列表失败: {e}")
        return ContentListResponse(
            success=False,
            data=[],
            total=0,
            page=page,
            size=size
        )

@router.get("/content/my", response_model=ContentListResponse)
async def get_my_content(
    page: int = 1,
    size: int = 20,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取我发布的内容"""
    try:
        from_ = (page - 1) * size
        
        query = db.query(Content).filter(Content.author_id == current_user.id)
        total = query.count()
        contents = query.order_by(Content.created_at.desc()).offset(from_).limit(size).all()
        
        content_list = []
        for content in contents:
            first_media = db.query(ContentMedia).filter(
                ContentMedia.content_id == content.id
            ).order_by(ContentMedia.sort_order).first()
            
            content_tags = db.query(ContentTag).filter(
                ContentTag.content_id == content.id
            ).all()
            tag_ids = [ct.tag_id for ct in content_tags]
            
            tag_names = []
            if tag_ids:
                tags = db.query(Tag.name).filter(Tag.id.in_(tag_ids)).all()
                tag_names = [tag[0] for tag in tags]
            
            content_list.append(ContentItem(
                id=content.id,
                title=content.title,
                description=content.description or "",
                author_id=content.author_id,
                author_nickname=current_user.nickname,
                status=content.status,
                view_count=content.view_count,
                like_count=content.like_count,
                comment_count=content.comment_count,
                share_count=content.share_count,
                collect_count=content.collect_count,
                first_image_url=first_media.media_url if first_media else None,
                tag_names=tag_names,
                created_at=content.created_at.isoformat() if content.created_at else "",
                published_at=content.published_at.isoformat() if content.published_at else None
            ))
        
        return ContentListResponse(
            success=True,
            data=content_list,
            total=total,
            page=page,
            size=size
        )
        
    except Exception as e:
        print(f"获取我的内容失败: {e}")
        return ContentListResponse(
            success=False,
            data=[],
            total=0,
            page=page,
            size=size
        )

@router.get("/content/{content_id}", response_model=ContentDetailResponse)
async def get_content_detail(
    content_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取内容详情"""
    try:
        # 查询内容
        content = db.query(Content).filter(Content.id == content_id).first()
        
        if not content:
            return ContentDetailResponse(
                success=False,
                message="内容不存在"
            )
        
        # 增加浏览次数
        content.view_count = (content.view_count or 0) + 1
        db.commit()
        
        # 获取媒体文件
        media_list = db.query(ContentMedia).filter(
            ContentMedia.content_id == content.id
        ).order_by(ContentMedia.sort_order).all()
        
        media_items = []
        for media in media_list:
            media_items.append(MediaItem(
                url=media.media_url,
                media_type=media.media_type,
                width=media.width,
                height=media.height,
                file_size=media.file_size,
                duration=media.duration
            ))
        
        # 获取标签
        content_tags = db.query(ContentTag).filter(
            ContentTag.content_id == content.id
        ).all()
        tag_ids = [ct.tag_id for ct in content_tags]
        
        tag_names = []
        if tag_ids:
            tags = db.query(Tag).filter(Tag.id.in_(tag_ids)).all()
            tag_names = [tag.name for tag in tags]
        
        # 获取作者信息
        author = db.query(User).filter(User.id == content.author_id).first()
        
        # 构建响应数据
        content_data = {
            "id": content.id,
            "title": content.title,
            "description": content.description or "",
            "author_id": content.author_id,
            "author_nickname": author.nickname if author else "未知",
            "status": content.status,
            "view_count": content.view_count,
            "like_count": content.like_count,
            "comment_count": content.comment_count,
            "share_count": content.share_count,
            "collect_count": content.collect_count,
            "media_list": [media.dict() for media in media_items],
            "tag_names": tag_names,
            "created_at": content.created_at.isoformat() if content.created_at else "",
            "published_at": content.published_at.isoformat() if content.published_at else None
        }
        
        return ContentDetailResponse(
            success=True,
            data=content_data
        )
        
    except Exception as e:
        print(f"获取内容详情失败: {e}")
        import traceback
        traceback.print_exc()
        return ContentDetailResponse(
            success=False,
            message=f"获取详情失败: {str(e)}"
        )

# ============ 视频分片上传接口 ============

@router.post("/content/upload/init")
async def init_chunk_upload(
    filename: str = Form(...),
    file_size: int = Form(...),
    content_type: str = Form("video/mp4"),
    current_user: User = Depends(get_current_user)
):
    """初始化分片上传会话"""
    try:
        # 验证文件大小
        if not chunk_upload_service.validate_file_size(file_size):
            return {
                "success": False,
                "message": f"文件大小超过限制（最大500MB）"
            }
        
        # 计算分片数量
        chunk_count = chunk_upload_service.calculate_chunk_count(file_size)
        
        # 创建上传会话
        session_id = chunk_upload_service.create_upload_session(
            file_name=filename,
            file_size=file_size,
            chunk_count=chunk_count,
            content_type=content_type
        )
        
        # 导入CHUNK_SIZE常量
        from services.chunk_upload_service import CHUNK_SIZE
        
        return {
            "success": True,
            "session_id": session_id,
            "chunk_size": CHUNK_SIZE,
            "chunk_count": chunk_count
        }
        
    except Exception as e:
        print(f"初始化分片上传失败: {e}")
        return {
            "success": False,
            "message": f"初始化失败: {str(e)}"
        }

@router.post("/content/upload/chunk")
async def upload_chunk(
    session_id: str = Form(...),
    chunk_number: int = Form(...),
    chunk_data: UploadFile = File(...),
    current_user: User = Depends(get_current_user)
):
    """上传分片"""
    try:
        # 读取分片数据
        data = await chunk_data.read()
        
        # 上传分片
        success = chunk_upload_service.upload_chunk(
            session_id=session_id,
            chunk_number=chunk_number,
            chunk_data=data
        )
        
        if success:
            # 获取进度
            progress = chunk_upload_service.get_upload_progress(session_id)
            return {
                "success": True,
                "progress": progress
            }
        else:
            return {
                "success": False,
                "message": "分片上传失败"
            }
        
    except Exception as e:
        print(f"分片上传失败: {e}")
        return {
            "success": False,
            "message": f"上传失败: {str(e)}"
        }

@router.get("/content/upload/progress/{session_id}")
async def get_upload_progress(
    session_id: str,
    current_user: User = Depends(get_current_user)
):
    """获取上传进度"""
    try:
        progress = chunk_upload_service.get_upload_progress(session_id)
        
        if progress["status"] == "not_found":
            return {
                "success": False,
                "message": "会话不存在"
            }
        
        return {
            "success": True,
            "progress": progress
        }
        
    except Exception as e:
        print(f"获取上传进度失败: {e}")
        return {
            "success": False,
            "message": f"获取进度失败: {str(e)}"
        }

@router.post("/content/upload/finish")
async def finish_chunk_upload(
    session_id: str = Form(...),
    title: str = Form(...),
    description: str = Form(None),
    tag_ids: str = Form("[]"),
    status: int = Form(2),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """完成分片上传并发布内容"""
    try:
        import json
        
        # 合并分片
        merged_file = chunk_upload_service.merge_chunks(session_id)
        
        if not merged_file:
            return {
                "success": False,
                "message": "文件合并失败"
            }
        
        # 获取会话信息
        session = chunk_upload_service.upload_sessions.get(session_id)
        if not session:
            return {
                "success": False,
                "message": "会话不存在"
            }
        
        # 上传到MinIO
        file_name = session["file_name"]
        object_name = f"videos/{datetime.now().strftime('%Y%m%d')}/{current_user.id}_{datetime.now().timestamp()}_{file_name}"
        
        minio_url = None
        
        # 确保static/uploads目录存在
        import shutil
        os.makedirs("static/uploads", exist_ok=True)
        
        if minio_client:
            try:
                # 先上传到MinIO
                minio_url = minio_client.upload_file(merged_file, object_name, session["content_type"])
                
                # 清理临时文件
                os.remove(merged_file)
            except Exception as e:
                print(f"MinIO上传失败: {e}")
                # 如果MinIO不可用，使用本地路径
                final_filename = os.path.basename(merged_file)
                final_path = f"static/uploads/{final_filename}"
                
                # 使用shutil.move支持跨驱动器
                shutil.move(merged_file, final_path)
                minio_url = f"/static/uploads/{final_filename}"
        else:
            # 直接移动到static目录
            final_filename = os.path.basename(merged_file)
            final_path = f"static/uploads/{final_filename}"
            
            # 使用shutil.move支持跨驱动器
            shutil.move(merged_file, final_path)
            minio_url = f"/static/uploads/{final_filename}"
        
        # 解析标签
        tag_ids_list = json.loads(tag_ids)
        
        # 创建内容记录
        content = Content(
            title=title,
            description=description or "",
            author_id=current_user.id,
            status=status,
            published_at=datetime.utcnow() if status == 2 else None
        )
        
        db.add(content)
        db.flush()
        
        # 创建标签关联
        for tag_id in tag_ids_list:
            content_tag = ContentTag(
                content_id=content.id,
                tag_id=tag_id
            )
            db.add(content_tag)
        
        # 创建媒体记录
        media = ContentMedia(
            content_id=content.id,
            media_url=minio_url,
            media_type="video",
            sort_order=1,
            file_size=session["file_size"]
        )
        db.add(media)
        
        db.commit()
        db.refresh(content)
        
        # 清理会话
        chunk_upload_service.cleanup_session(session_id)
        
        return {
            "success": True,
            "message": "内容发布成功",
            "content_id": content.id
        }
        
    except Exception as e:
        print(f"完成上传失败: {e}")
        import traceback
        traceback.print_exc()
        return {
            "success": False,
            "message": f"发布失败: {str(e)}"
        }

